import { useRefValue } from '@gnlab/utils/env-react'
import { type RefObject } from 'react'
import { type AtMembers, type AtMember, makeElementId } from './members'

/**
 * 处理列表交互/成员高亮
 * 细节：如果在有“高亮成员”的情况下用户又执行了移动鼠标、搜索等操作，说明此高亮成员大概率不是用户想要选的成员
 */
export function useHighlight(
  members: AtMembers,
  listRef: RefObject<HTMLElement>,
  onConfirm: (member: AtMember) => void,
) {
  const membersRef = useRefValue(members)

  const [highlight, setHighlight] = useState('0')
  const highlightRef = useRefValue(highlight)

  // 屏蔽列表内的 mousedown 事件冒泡（见 ./view.ts 中对 mousedown 事件的说明）
  useEffect(() => {
    const list = listRef.current
    if (!list) return
    const prevent = (e: MouseEvent) => e.stopPropagation()
    list.addEventListener('mousedown', prevent)
    return () => list.removeEventListener('mousedown', prevent)
  }, [listRef])

  // members 变化时，重置高亮成员、列表滚动回最上面
  useEffect(() => {
    setHighlight(members[0].userId)
    if (listRef.current) listRef.current.scrollTo(0, 0)
  }, [members, listRef])

  // 通过键盘上、下键调整高亮
  const preventMouseTimeout = useRef<NodeJS.Timeout | null>(null) // 键盘触发后一定时间内屏蔽鼠标触发，不然在涉及滚动条滚动时会有交互冲突
  const keySetHighlight = useCallback((userId: string) => {
    if (preventMouseTimeout.current) clearTimeout(preventMouseTimeout.current)
    preventMouseTimeout.current = setTimeout(() => {
      preventMouseTimeout.current = null
    }, 300)

    setHighlight(userId)
    document.getElementById(makeElementId(userId))?.scrollIntoView({ block: 'nearest' })
  }, [])

  useEffect(() => {
    function listener(e: KeyboardEvent) {
      const isUp = e.key === 'ArrowUp'
      const isDown = e.key === 'ArrowDown'
      if (!isUp && !isDown) return

      e.preventDefault()

      const members = membersRef.current
      const index = members.findIndex(member => member.userId === highlightRef.current)
      if (index === -1) return
      if (isUp && index > 0) keySetHighlight(members[index - 1]!.userId)
      if (isDown && index < members.length - 1) keySetHighlight(members[index + 1]!.userId)
    }
    document.addEventListener('keydown', listener)
    return () => document.removeEventListener('keydown', listener)
  }, [membersRef, highlightRef, keySetHighlight])

  // 鼠标悬停调整高亮
  const mouseSetHighlight = useCallback(
    (userId: string) => {
      if (preventMouseTimeout.current === null) setHighlight(userId)
    },
    [preventMouseTimeout],
  )

  // 按下回车时提交当前高亮成员
  useEffect(() => {
    const handleEnter = (e: KeyboardEvent) => {
      if (e.key === 'Enter' || e.code === 'Enter') {
        e.preventDefault()
        e.stopPropagation()
        const member = membersRef.current.find(v => v.userId === highlightRef.current)!
        onConfirm(member)
      }
    }
    document.addEventListener('keydown', handleEnter)
    return () => document.removeEventListener('keydown', handleEnter)
  }, [membersRef, highlightRef, onConfirm])

  return { highlight, mouseSetHighlight }
}
